<?php
 class KeyValueStorageFile implements iAscetKeyValueStorage{
  var $folder;
  var $prefix;
  var $settings;
  protected $lock;

  function __construct($settings){
   if (!isset($settings->storage_type)){
    $settings->storage_type = self::StorageTemporary;
   }
   switch($settings->storage_type){
    case self::StorageTemporary: $this->folder=sys_get_temp_dir();       break;
    case self::StorageConstant:  $this->folder=$_SERVER['DOCUMENT_ROOT'];break;
    default: throw new KeyValueException('Constructor settings is malformed. Storage type can not be equal '.$settings->storage_type, 1);
   }
   if (isset($settings->folder)){
    $this->folder=$settings->folder;
   }

   if (!isset($settings->region_type)){
    $settings->region_type=self::RegionDomain;
   }
   switch($settings->region_type){
    case self::RegionDomain:
     $this->prefix=sha1(preg_replace('|^(www\\.)?([a-z0-9.-]+)(\\:[0-9])?|', '$2', strtolower($_SERVER['HTTP_HOST']))).'_';
     break;
    case self::RegionServer:
     $this->prefix='';
     break;
    case self::RegionFolder:
     $this->prefix=sha1(strtolower($_SERVER['DOCUMENT_ROOT'])).'_';
     break;
    default: throw new KeyValueException('Constructor settings is malformed. Region type can not be equal '.$settings->region_type, 1);
   }

   $this->storage=$settings;
  }

  function get_value($key, $default_value=''){
   $data=$this->get_value_full($key);
   return ($data==null) ? $default_value : $data->value;
  }

  function set_value($key, $value, $expires_time=86400){
   $backtrace=debug_backtrace();
   $data=(object)array(
    'time_create' =>time(),
    'time_expires'=>time()+$expires_time,
    'host'        =>$_SERVER['HTTP_HOST'],
    'value'       =>$value,
    'init_file'   =>$backtrace[0]['file'],
    'init_line'   =>$backtrace[0]['line']
   );
   unset($backtrace);
   $this->get_lock($key);
   $temporary_filename=$this->get_filename($key).'.tmp';
   $result=@file_put_contents($temporary_filename, serialize($data), LOCK_EX);
   rename($temporary_filename, $this->get_filename($key));
   if ($result===false){
    throw new KeyValueException('Can not save value', 3);
   }
   $this->release_lock();
  }

  function get_value_full($key){
   $this->get_lock($key);
   $buf     =@file_get_contents($this->get_filename($key));
   $this->release_lock();
   if ($buf===false){
    return null;
   }
   // @todo Проверять expires
   // @todo Проверять unserialize
   $data    =unserialize($buf);
   return $data;
  }

  protected function get_filename($key){
   return $this->folder.DIRECTORY_SEPARATOR.'ascetkey_'.$this->prefix.sha1($key).'.dat';
  }

  protected function get_lock($key){
   $this->lock = new SmartMutex('ascetkey_'.$key, SmartMutex::SmartMutex_Server);
   $this->lock->get_lock();
  }

  protected function release_lock(){
   $this->lock = null;
  }

  function delete_value($key){
   $this->get_lock($key);
   @unlink($this->get_filename($key));
   $this->release_lock();
  }
 }


?>